/**
 * 
 */
package com.ms.player;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.ms.player.message.SUpdatePlayerAttribute;
import com.xpec.c4.game.utility.GUID;
import com.xpec.c4.message.ConstantCode;
import com.xpec.c4.message.MessageTypes;
import com.xpec.c4.service.message.MessageAction;
import com.xpec.c4.service.module.ServerProperties;

/**
 * 角色屬性變更清單管理器
 * 
 * @author TW15010
 */
public class UpdateAttributeList implements Serializable {
	private static final long serialVersionUID = 265417420105746451L;

	private static final Log log = LogFactory.getLog(UpdateAttributeList.class);

	/**
	 * 記錄有被變更過的屬性<br>
	 * key: 屬性 id {@link PlayerAttributeType}<br>
	 * value: 更新內容
	 */
	private HashMap<Integer, UpdateAttribute> updateAttrMap = new HashMap<Integer, UpdateAttribute>();

	/**
	 * 增加更新過的屬性到更新列表 {@link #updateAttrMap} 中
	 * 
	 * @param attrId
	 *            屬性id {@link PlayerAttributeType}
	 * @param attrValue
	 *            更新後的屬性數值
	 */
	public void addUpdateValue(int attrId, String attrValue) {
		UpdateAttribute updateAttr;
		if (!updateAttrMap.containsKey(attrId)) {
			updateAttr = new UpdateAttribute();
			updateAttr.setId(attrId);
			updateAttrMap.put(attrId, updateAttr);
		} else {
			updateAttr = updateAttrMap.get(attrId);
		}

		updateAttr.setValue(attrValue);
	}

	public void addUpdateValue(int attrId, int attrValue) {
		addUpdateValue(attrId, String.valueOf(attrValue));
	}
	
	public void addUpdateValue(int attrId, long attrValue) {
		addUpdateValue(attrId, String.valueOf(attrValue));
	}
	
	public void addUpdateValue(int attrId, BigDecimal attrValue) {
		addUpdateValue(attrId, String.valueOf(attrValue));
	}
	
	public void addUpdateValue(int attrId, Boolean attrValue) {
		addUpdateValue(attrId, String.valueOf(attrValue));
	}

	/**
	 * 取得更新過的屬性列表
	 * 
	 * @return 屬性列表
	 */
	public ArrayList<UpdateAttribute> getUpdateList() {
		ArrayList<UpdateAttribute> updatedAttrList = new ArrayList<UpdateAttribute>(updateAttrMap.values());

		return updatedAttrList;
	}

	/**
	 * 清除變更過的屬性列表
	 */
	public void clear() {
		updateAttrMap.clear();
	}

	/**
	 * 將外部的屬性更新項目套到角色身上
	 * 
	 * @param updatedAttrList
	 *            屬性更新清單
	 * @param player
	 *            角色資料
	 */
	public static void applyUpdateListToPlayer(ArrayList<UpdateAttribute> updatedAttrList, Player player) {
		if (updatedAttrList == null) {
			return;
		}

		if (player == null) {
			return;
		}

		for (UpdateAttribute attr : updatedAttrList) {
			switch (attr.getId()) {
			case PlayerAttributeType.GOLD_COIN:
				player.setgoldCoin(attr.getValueBigDecimal());
				break;

			case PlayerAttributeType.TRIAL_COIN:
				player.setTrialCoin(attr.getValueBigDecimal());
				break;

			case PlayerAttributeType.LUCKY_COIN:
				player.setLuckyCoin(attr.getValueBigDecimal());
				break;

			case PlayerAttributeType.LEVEL:
				player.setLevel(attr.getValueInt());
				break;

			case PlayerAttributeType.VIP:
				player.setVip(attr.getValueInt());
				break;

			case PlayerAttributeType.SILENT_EXPIRE_TIME:
				player.setSilentExpireTime(attr.getValueLong());
				break;

			case PlayerAttributeType.NAME:
				player.setName(attr.getValue());
				break;

			case PlayerAttributeType.EXP:
				player.setExp(attr.getValueBigDecimal());
				break;

			case PlayerAttributeType.BANK_GOLD_COIN:
				player.setBankGoldCoin(attr.getValueBigDecimal());
				break;

			case PlayerAttributeType.MONTHLY_FEE_END_TIME:
				player.setMonthlyFeeEndTime(attr.getValueLong());
				break;

			case PlayerAttributeType.WEEKLY_FEE_END_TIME:
				player.setWeeklyFeeEndTime(attr.getValueLong());
				break;

			case PlayerAttributeType.LAST_GET_LUCKY_COIN_TIME:
				player.setLastGetLuckyCoinTime(attr.getValueLong());
				break;

			case PlayerAttributeType.MONTHLY_AWARD_TIME:
				player.setMonthlyAwardTime(attr.getValueLong());
				break;
				
			case PlayerAttributeType.WEEKLY_AWARD_TIME:
				player.setWeeklyAwardTime(attr.getValueLong());
				break;
				
			case PlayerAttributeType.PURCHASE_REWARD_COUNT:
				player.setFirstStoreReward(attr.getValueInt());
				break;
				
			case PlayerAttributeType.OFFLINE_PLAY_RESULT:
				player.setOfflinePlayResult(attr.getValue());
				break;

			case PlayerAttributeType.VIP_EXP:
				player.setVipExp(attr.getValueLong());
				break;

			case PlayerAttributeType.STORE_REWARD_CONTINUOUS_LOGIN_COUNT:
				player.setStoreRewardContinuousLoginCount(attr.getValueInt());
				player.setHaveFirstStoreCharacter(true);
				break;	

			case PlayerAttributeType.INVITE_CODE:
				player.setInviteCode(attr.getValue());
				break;
				
			case PlayerAttributeType.CRYSTAL:
				player.setCrystal(attr.getValueInt());
				break;
				
			case PlayerAttributeType.BAN_TALK_TIME_BY_GMTOOL:
				player.setBanTalkTime(attr.getValueLong());
				break;
				
			case PlayerAttributeType.AUTHENTICATE:
				player.setVerifiedMember(attr.getValueBoolean());
				break;
				
			case PlayerAttributeType.EXP_IN_CURRENT_LEVEL:
				player.addUpdateExpInCurrentLevel(attr.getValueLong());
				break;
				
			case PlayerAttributeType.EXP_TO_NEXT_LEVEL:
				player.addUpdateExpToNextLevel(attr.getValueLong());
				break;
				
			default:
				if (log.isErrorEnabled()) {
					log.error("applyToPlayer() unknow attribute type " + attr.getId());
				}
				break;
			}
		}
	}

	/**
	 * 將儲存的屬性更新項目套到角色身上
	 * 
	 * @param player
	 *            角色資料
	 */
	public void applyToPlayer(Player player) {
		if (player == null) {
			return;
		}

		ArrayList<UpdateAttribute> updatedAttrList = getUpdateList();

		applyUpdateListToPlayer(updatedAttrList, player);
	}

	/**
	 * 將有變更過的屬性一次送給 client
	 * 
	 * @param sessionId
	 *            client session id
	 */
	public void sendToClient(GUID playerId, GUID sessionId, int userType) {
		// 屬性有數值更新
		if (updateAttrMap.size() == 0) {
			return;
		}

		// 取得更新過的屬性列表
		ArrayList<UpdateAttribute> updatedAttrList = getUpdateList();

		// 消息內容
		SUpdatePlayerAttribute data = new SUpdatePlayerAttribute();
		data.setUpdatedAttrList(updatedAttrList);

		// 送出
		MessageAction.sendMessage(sessionId, MessageTypes.S_ZONE_UPDATE_PLAYER_ATTRIBUTE, data);
		
		if (log.isInfoEnabled() && ServerProperties.isSaveConsoleLog(userType)) {
			StringBuilder sb = new StringBuilder();
			sb.append("send update player " + playerId + " attribute ");
			for (UpdateAttribute attr : updatedAttrList) {
				String attrName = ConstantCode.getName(PlayerAttributeType.class, attr.getId());
//				String value = attr.getValueBigDecimal().toString();
				String value = attr.getValue();
				sb.append(attrName + "=" + value + " ");
			}

			log.info(sb.toString());
		}

		// 清除列表
		clear();
	}
}